//
// Windmill adventure object handling. Randomly awards 4-6 units of k_crystal,
// k_sulfur, k_mercury, or k_gems every 7 days
//
// L. Dean Gibson II  2/21/01
//

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "adv_windmill.h"

#include "adventure_ai.h"
#include "adventure_sounds.h"
#include "army.h"
#include "basic_dialog.h"
#include "external_string.h"
#include "materials.h"
#include "music.h"
#include "object_registration.h"
#include "player.h"
#include "player_color.h"
#include "random.h"
#include "replace_keywords.h"
#include "simple_dialog.h"
#include "sized_int_types.h"
#include "streambuf_operators.h"

namespace
{
	int const k_current_map_format_version = 2;
	int const k_current_save_format_version = 1;

	static t_object_registration<t_adv_windmill> k_registration( k_adv_object_windmill );
	
	inline int to_base_map_format_version( int format_version )
	{
		return format_version;
	}
	
	inline int to_base_save_format_version( int format_version )
	{
		if ( format_version == 0 )
			return 1;
		else 
			return 2;
	}
}

// -------------------------------------------------------------------
// Windmill constructor
// -------------------------------------------------------------------
t_adv_windmill::t_adv_windmill( std::string const& model_name )
                  : t_owned_scriptable_adv_object( model_name )
{
	m_production_time = 0;
	reset();
}

t_material t_adv_windmill::get_material() const
{
	return m_material.material;
}

// -------------------------------------------------------------------
// generator which produces material once per week
// -------------------------------------------------------------------
int t_adv_windmill::get_production()
{
	return m_material.amount;
}

// -------------------------------------------------------------------
// generator which produces material once per week
// -------------------------------------------------------------------
int t_adv_windmill::get_version() const
{
	return k_current_save_format_version;
}

// -------------------------------------------------------------------
// generator which produces material once per week
// -------------------------------------------------------------------
void t_adv_windmill::reset()
{
	randomize_production();
}

// -------------------------------------------------------------------
// generator which produces material once per week
// -------------------------------------------------------------------
void t_adv_windmill::activate_trigger( t_army* army, t_adv_map_point const& point, 
		                                   t_direction direction, t_adventure_frame* frame )
{
	t_sound_cache music = get_music_playing();

	if (army->is_human())
	{
		stop_music();
		get_dialog_sound( k_dialog_sound_treasure )->play( get_sound_volume() );
	}

	if ( is_ally( army->get_owner(), get_owner() ) )
	{
		if (army->is_human())
		{
			ok_dialog( get_text( "refused_ally" ), get_dialog_bottom( point ), get_name() );
			play_music( music );
		}
		return;
	}

	if ( army->get_owner_number() != get_owner_number())
	{
		if (army->get_living_hero_count() == 0)
		{
			if (army->is_human())
			{
				ok_dialog( get_text( "no_heroes" ), true );
			}
			return;
		}
		set_owner( army->get_owner_number() );  
	}

	if (army->get_owner() == NULL)
	{
		if (army->is_human())
			play_music( music );
		return;  // do nothing further, wandering monster hit us
	}

	if (m_production_time == 0)
		get_owner()->gain( m_material.material, m_material.amount );

	if (!army->get_owner()->is_computer())
	{
		std::string					  text;
		std::string					  production;
		t_counted_ptr<t_basic_dialog> dialog = new t_basic_dialog;

		if (m_production_time == 0)
		{
			dialog->add_material( m_material.material, m_material.amount );
			text = get_text( "initial" );
			text = replace_keywords( text, m_material.amount, m_material.material );
		}
		else
			text = get_text( "empty" );
		dialog->set_text( text );
		dialog->add_ok_button();
		dialog->set_title( get_name() );
		dialog->open( get_dialog_bottom( point ), true, k_align_bottom );
		dialog->run_modal();
		if (army->is_human())
			play_music( music );
	}
	if (m_production_time == 0)
		m_production_time = 7;
}

// -------------------------------------------------------------------
// generator which produces material once per week
// -------------------------------------------------------------------
void t_adv_windmill::place( t_adventure_map& map, t_adv_map_point const& point )
{
	randomize_production();

	t_owned_scriptable_adv_object::place( map, point );
}

// -------------------------------------------------------------------
// generator which produces material once per week
// -------------------------------------------------------------------
void t_adv_windmill::process_new_day()
{
	if (m_production_time > 0)
		m_production_time--;
	if (m_production_time == 0 && get_owner_number() >= 0)
	{
		get_owner()->gain( m_material.material, m_material.amount );
		reset();
		m_production_time = 7;
	}
}

// -------------------------------------------------------------------
// generator which produces material once per week
// -------------------------------------------------------------------
void t_adv_windmill::randomize_production()
{
	// randomly determine our production amount and production material
	switch (random(4)) {
	case 0:
		m_material.material = k_crystal;
		break;
	case 1:
		m_material.material = k_sulfur;
		break;
	case 2:
		m_material.material = k_mercury;
		break;
	case 3:
		m_material.material = k_gems;
		break;
	}

	// randomly determine our production amount
	m_material.amount = random(3) + 4;
}

// -------------------------------------------------------------------
// generator which produces material once per week
// -------------------------------------------------------------------
bool t_adv_windmill::read(  std::streambuf &					stream,
							t_qualified_adv_object_type const &	type,
							int									version )
{
	if ( version < 0 || version > k_current_save_format_version )
		return false;

	if ( !t_owned_scriptable_adv_object::read( stream, type, to_base_save_format_version( version ) ) )
		return false;

	if ( version >= 1 )
	{
		m_material.material = t_material( get< t_uint8 >( stream ) );
		m_material.amount = get< t_uint8 >( stream );
		m_production_time = get< t_uint8 >( stream );
	}

	return true;	
}

// -------------------------------------------------------------------
// generator which produces material once per week
// -------------------------------------------------------------------
bool t_adv_windmill::read_from_map( std::streambuf& buffer, t_progress_handler* handler )
{
	int format_version = get< t_uint16 >( buffer );
	
	if ( format_version < 0 || format_version > k_current_map_format_version )
		return false;

	return	t_owned_scriptable_adv_object::read_from_map(
				buffer,
				handler,
				to_base_map_format_version( format_version ) );
}

// -------------------------------------------------------------------
// generator which produces material once per week
// -------------------------------------------------------------------
bool t_adv_windmill::write( std::streambuf & stream ) const
{
	if ( !t_owned_scriptable_adv_object::write( stream ) )
		return false;

	put< t_uint8 >( stream, m_material.material );
	put< t_uint8 >( stream, m_material.amount );
	put< t_uint8 >( stream, m_production_time );

	return true;
}

// -------------------------------------------------------------------
// generator which produces material once per week
// -------------------------------------------------------------------
float t_adv_windmill::ai_value( t_adventure_ai const& ai, t_creature_array const& army, int move_cost ) const
{
	t_player* player = army.get_owner();

	if (army.get_living_hero_count() == 0)
		return 0.0f;
	t_material_values const& values = player->get_material_values();
	return values[m_material.material] * m_material.amount * 1.2f * ai.scale_for_aggression( player, get_owner() ) ;
}

